package org.zn.mvcbase.rest;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.zn.commons.collection.Maps;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class RestEntity {

	private RestTemplate restTemplate;

	private HttpMethod method;

	private HttpEntity<?> requestEntity;

	private String url;

	private Map<String, Object> variables;

	private ObjectMapper objectMapper;

	public RestTemplate getRestTemplate() {
		return restTemplate;
	}

	public void setRestTemplate(RestTemplate restTemplate) {
		this.restTemplate = restTemplate;
	}

	public HttpMethod getMethod() {
		return method;
	}

	public void setMethod(HttpMethod method) {
		this.method = method;
	}

	public RestEntity GET() {
		this.method = HttpMethod.GET;
		return this;
	}

	public RestEntity POST() {
		this.method = HttpMethod.POST;
		return this;
	}

	public RestEntity HEAD() {
		this.method = HttpMethod.HEAD;
		return this;
	}

	public RestEntity OPTIONS() {
		this.method = HttpMethod.OPTIONS;
		return this;
	}

	public RestEntity PATCH() {
		this.method = HttpMethod.PATCH;
		return this;
	}

	public RestEntity PUT() {
		this.method = HttpMethod.PUT;
		return this;
	}

	public RestEntity DELETE() {
		this.method = HttpMethod.DELETE;
		return this;
	}

	public RestEntity TRACE() {
		this.method = HttpMethod.TRACE;
		return this;
	}

	public HttpEntity<?> getRequestEntity() {
		return requestEntity;
	}

	public void setRequestEntity(HttpEntity<?> requestEntity) {
		this.requestEntity = requestEntity;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public Map<String, Object> getVariables() {
		return variables;
	}

	public void setVariables(Map<String, Object> variables) {
		this.variables = variables;
	}

	private void bindingUrL(Map<String, Object> variables) {

		String var = "";

		Set<String> ks = variables.keySet();

		for (String k : ks) {

			var += k + "={" + k + "}&";

		}

		if (var.endsWith("&"))
			var = var.substring(0, var.length() - 1);

		String[] urls = url.split("\\?");

		if (urls.length == 1) {

			url += "?" + var;

		} else {

			url += var;

		}

	}
	
	
	public RestEntity addUrlVariables(Map<String, Object> variables) {
		if (this.variables == null) {
			this.variables = variables;
		}
			this.variables.putAll(variables);
		
		
		return this;
	}
	
	public RestEntity addUrlVariable(String key,Object value) {
		if (this.variables == null) {
			this.variables = Maps.newMap();
		} 
			
		this.variables.put(key, value);
		
		
		return this;
	}
	

	public RestEntity addVariables(Map<String, Object> variables) {

		if (this.variables == null) {
			this.variables = variables;
		} 
			this.variables.putAll(variables);
		
		
		bindingUrL(variables);
		
		return this;

	}

	public RestEntity addVariables(Object entity) throws IOException {

		Map<String, Object> varmap = null;

		if (entity != null) {

			byte[] bys = objectMapper.writeValueAsBytes(entity);

			varmap = objectMapper.readValue(bys, Map.class);

		}

		if (this.variables == null) {
			this.variables = varmap;
		} else {
			this.variables.putAll(varmap);
		}
		
		bindingUrL(variables);
		
		return this;

	}

	public ObjectMapper getObjectMapper() {
		return objectMapper;
	}

	public void setObjectMapper(ObjectMapper objectMapper) {
		
		this.objectMapper = objectMapper;
	}

	public void setHeader(Map<String, List<String>> addheaders) {
		
//		HttpHeaders header= requestEntity.getHeaders();
//		
//		addheaders.putAll(header);

		HttpEntity<?> httpEntity=new HttpEntity<>(addheaders);
		
		this.requestEntity=httpEntity;
	}

	public EntityBody sendRequest() throws JsonProcessingException, IOException {

		ResponseEntity<String> re = restTemplate.exchange(url, method, requestEntity, String.class, variables != null ? variables : new HashMap<>());
		
		JsonNode jn = objectMapper.readTree(re.getBody());

		EntityBody eb = new EntityBody(jn, objectMapper, re.getHeaders(), re.getStatusCode());

		return eb;

	}


	public ResponseEntity<String> exchange() throws JsonProcessingException, IOException {

		ResponseEntity<String> re = restTemplate.exchange(url, method, requestEntity, String.class, variables != null ? variables : new HashMap<>());


		return re;

	}

}
